﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using PaperRenderingInterfaces;
using RenderEngineInterfaces;
using HtmlAgilityPack;
using PaperPluginUtilities;
using DeepZoomPivotConstructor.PivotLib;
using DeepZoomPivotConstructor.VisualLib;

namespace HTMLTablePageScanner
{
    /// <summary>
    /// Scan a table for images. Instead of expecting things to be
    /// on every single row, it expects all the info to be contained in
    /// a single cell - for the whole web page.
    /// </summary>
    [Export(typeof(IPaperRender))]
    [PaperRender("HTMLSimpleTableCells")]
    public class WebTableCellScanner : IPaperRender
    {
        /// <summary>
        /// Fetch info from the web
        /// </summary>
        [Import]
        IWebAccess WebGetter;

        /// <summary>
        /// Render to visuals whatever it is we are looking at
        /// </summary>
        [Import]
        IRenderEngine MyRender;

        /// <summary>
        /// Scan the web page that is given!
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        public IEnumerable<DeepZoomPivotConstructor.PivotLib.PivotImage> Render(string renderAddress)
        {
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(WebGetter.GetUriAsString(new Uri(renderAddress)));

            var images = new EnumerableWrapper<HtmlNode>(doc.DocumentNode.SelectNodes("//td"))
                .SelectMany(i => FindImagesInCell(i, new Uri(renderAddress)))
                .Apply(i => i.Add("More Information", "Note Web Page", new Uri(renderAddress)));

            return images;
        }

        /// <summary>
        /// Find all the images in a particular cell.
        /// </summary>
        /// <param name="cellHtml"></param>
        /// <returns></returns>
        private IEnumerable<PivotImage> FindImagesInCell(HtmlNode cellHtml, Uri baseUri)
        {
            List<ImageUrlParsing.LinkInfo> links = new List<ImageUrlParsing.LinkInfo>();

            ///
            /// Look for links
            /// 

            cellHtml.ScanSubNodes("a").Execute(linkNode =>
            {
                ImageUrlParsing.LinkInfo info;
                var hrefAttr = linkNode.Attributes["href"];
                if (hrefAttr != null)
                {
                    info.url = hrefAttr.Value;
                    info.urlName = linkNode.InnerText.CleanHTMLText();
                    if (info.urlName == null || info.urlName.Length == 0)
                    {
                        info.urlName = ImageUrlParsing.GetPictureFileName(info.url);
                    }
                    links.Add(info);
                }
            });

            ///
            /// Some of the links may be to more than a single picutre, but with multiple
            /// formats
            /// 

            var groupedImages = from l in links
                                where ImageUrlParsing.IsPictureType(l.url)
                                group l by ImageUrlParsing.GetPictureFileName(l.url);

            ///
            /// And then convert those guys to images.
            /// 

            var images = groupedImages.Select(ls =>
                {
                    var info = ImageUrlParsing.GetBestImage(ls);
                    Visual v = MyRender.Render(new Uri(baseUri, info.url), forceAsComposableUnit: true);
                    PivotImage p = new PivotImage(v);
                    p.Name = info.urlName;

                    ls.Execute(l => p.Add("Graphics Files", ImageUrlParsing.GetNormalizedFileExtension(l.url), new Uri(baseUri, l.url)));

                    DateTime? whenModified = WebGetter.GetLastModificationTime(new Uri(baseUri, info.url));
                    if (whenModified.HasValue)
                    {
                        p.Add("Date", whenModified.Value);
                    }
                    else
                    {
                        p.Add("Date", DateTime.Now);
                    }

                    p.Add("Caption", "<none specified>");

                    return p;
                });

            return images;
        }
    }
}
